跳到主要内容

状态机

这里指服务端自定义状态机,即服务器单位上的状态机。一个单位可以有多个状态机,这些状态机同时生效tick。 比如技能是一个状态机,而移动也是一个状态机,单位可以一边移动一边放技能。技能、移动等状态机是服务器逻辑写好的,不可更改。 可以添加额外的状态机来管理单位的行为。 服务端状态机创建时可以同步给客户端,即在客户端创建一个一样结构的状态机。然后客户端通过on_enter, on_update, on_exit回调来实现动画播放的逻辑

状态机创建与同步

状态机附属于单位,由单位创建状态机,和同步状态机

get_or_create_state_machine

创建自定义服务端状态机,如果已经存在就返回存在的状态机

  • 参数

    • name (string) - 状态机名字,同一个单位上的状态机名字不能重复。注意不要使用形如"skill"的名字,这些被默认状态机占用了
    • sync (bool) - 是否将状态机同步给客户端,不填默认false。同步给客户端的作用是让客户端的单位上创建一个同样结构的状态机来播动画。
  • 返回

    • sm (table) - 状态机lua对象
    • new (bool) - 是否是新创建的
local sm, new = unit:get_or_create_state_machine('taunt', true)

sync_state_machines

单位同步状态机到客户端。一般是服务器状态机建好之后再同步,减少通信成本。 状态机名字是唯一id。首先客户端会清理服务端没有的同步状态机(不会清理客户端独有的状态机) 然后添加服务端同步过来的新状态机,如果客户端已经有同名的,则不处理。 参见客户端 lua里base.event.on_unit_state_machine_changed的逻辑

unit:sync_state_machines()

状态机api

add_state

状态机添加状态,如果id已经有了就返回已经有的状态 注意:创建状态机的时候状态机默认创建id为-1, name为'exit'的状态,并且状态机的当前状态为'exit'

由c++实现的api

  • 参数
    • name (string) - 状态名(只是起描述性作用)
    • id (int) - 状态id
  • 返回
    • state (table) - state的lua对象
local state = sm:add_state('idle', 0)

get_state

根据id获取状态机的状态

由c++实现的api

  • 参数

    • id (int) - 状态id
  • 返回

    • state (table) - state的lua对象
local exit_state = sm:get_state(-1)

set_current_state

根据id设置状态机的当前状态

由c++实现的api

  • 参数
    • id (int) - 状态id, 注意id对应的状态必须先添加到状态机,否则不生效
sm:set_current_state(id)

transit

状态机根据event id切换状态

  • 参数
    • id (uint8) - 事件id(>=0且<=255), 注意id对应的事件必须先添加到状态转移表里,否则不生效
sm:transit(id)

set_priority

仅对同步状态机有效,用于设置同步到客户端的状态机的priority

  • 参数
    • priority (uint) - 大于等于0的数字表示优先级,注意客户端移动状态机的优先级是0,技能状态机的优先级是1。所以一般自定义状态机优先级应该大于等于2
sm:set_priority(3)

set_layer

仅对同步状态机有效,用于设置同步到客户端的状态机的layer, layer控制动画影响全身还是半身

  • 参数
    • layer (uint) - 仅能取值0,1,2. 0表示影响全身,1表示影响上半身,2表示影响下半身
sm:set_layer(1)

状态api

add_transition

状态添加转移表,即什么事件可以使状态机从当前状态切换到下一个状态

  • 参数
    • id (uint8) - 事件id,可以用enum来封装以明确含义,但是api接收的是uint8
    • next(table)- 下一个状态的lua对象
local idle_state = sm:get_state(0)
local exit_state = sm:get_state(-1)
local event = {idle=0, exit=1}
exit_state:add_transition(event.idle, idle_state)
idle_state:add_transition(event.exit, exit_state)

回调

状态切换的时候会触发回调 回调调用顺序:比如从idle状态切换到walk状态,先调用idle:on_exit(), 再调用walk:on_enter(), 然后每帧调用walk:on_update(delta)

on_enter

进入状态的时候调用

  • 参数
    • self (table) - 状态的lua对象
local idle_state = sm:get_state(0)
function idle_state:on_enter()
log.info('enter idle state')
end

on_update

状态tick的时候调用

  • 参数
    • self (table) - 状态的lua对象
    • delta (float) - 更新的delta时间,单位秒
local idle_state = sm:get_state(0)
function idle_state:on_update(delta)
log.info('update idle state, time elapsed', delta)
end

on_exit

离开状态的时候调用

  • 参数
    • self (table) - 状态的lua对象
local idle_state = sm:get_state(0)
function idle_state:on_exit()
log.info('leave idle state')
end